  #include "tcpserver.h"
#include"../kernel/tcpkernel.h"
TCPServer::TCPServer()
{
    m_socklisten = 0;
    m_bFlagQuit = true;
    FD_ZERO(&m_fdsets);
}
TCPServer::~TCPServer()
{

}

bool TCPServer::initNetWork(const char *szip, short nport)
{
    //初始化winsock
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
    wVersionRequested = MAKEWORD(2, 2);

    err = WSAStartup(wVersionRequested, &wsaData);
    //WSAStartup与WSACleanup 配套
    if (err != 0) {

        printf("WSAStartup failed with error: %d\n", err);
        return false;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
       unInitNetWork("Could not find a usable version of Winsock.dll\n");
        return false;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");

    m_socklisten =  socket(AF_INET,SOCK_STREAM,0);
    //SOCK_STREAM表示tcp字节流
    if(INVALID_SOCKET == m_socklisten){
        unInitNetWork("socket err\n");
        return false;
    }

    sockaddr_in addrserver;//客户端地址
    addrserver.sin_family = AF_INET;
    addrserver.sin_port = htons(nport);
    addrserver.sin_addr.s_addr = 0;
    if(SOCKET_ERROR == bind(m_socklisten,(const sockaddr*)&addrserver,sizeof(addrserver))){
        unInitNetWork("bind err\n");
        return false;
    }
    if(SOCKET_ERROR == listen(m_socklisten,10)){
       unInitNetWork("listen err\n");
        return false;
    }
   //创建线程
    HANDLE hThread = CreateThread(0,0,&ThreadAccept,this,0,0);
    if(hThread)
        m_lstThread.push_back(hThread);
    //单线程轮询接收所有的客户端
    hThread = CreateThread(0,0,&ThreadRecv,this,0,0);
    if(hThread){
        m_lstThread.push_back(hThread);
    }
    return true;
}

DWORD TCPServer::ThreadAccept(LPVOID lpvoid)
{
    TCPServer *pthis = (TCPServer*)lpvoid;
    sockaddr_in addrclient;
    int nsize = sizeof(addrclient);
    //DWORD dwThreadId;
    u_long iMode = 1;
    while(pthis->m_bFlagQuit){
        SOCKET sockWaiter =  accept(pthis->m_socklisten,(struct sockaddr*)&addrclient,&nsize);
        printf("client ip:%s nport:%d\n",inet_ntoa(addrclient.sin_addr),addrclient.sin_port);
       //加入到集合内
        FD_SET(sockWaiter,&pthis->m_fdsets);
        //将sockWaiter设置为非阻塞
        //ioctlsocket(sockWaiter, FIONBIO, &iMode);
        //将sockWaiter加入链表中
       // pthis->m_lstSocket.push_back(sockWaiter);
    }

    return 0;
}

DWORD TCPServer::ThreadRecv(LPVOID lpvoid)
{
    TCPServer *pthis = (TCPServer*)lpvoid;

    pthis->recvData();
    return 0;
}
void TCPServer::recvData()
{
    int nPackSize;//当前任务剩余总字节数
    int nRecvNum;//已接收字节数
    char *pszbuf = NULL;
    SOCKET sockWaiter;
    fd_set fdtemp;
    TIMEVAL  tv;
    tv.tv_sec =0;
    tv.tv_usec = 100;
    while(m_bFlagQuit){
         //接收包大小
        fdtemp = m_fdsets;
        //将集合交给select查看
        select(0,&fdtemp,0,0,&tv);
        //校验是否发生网络事件
        for(int i =0; i < m_fdsets.fd_count;i++){
            if(FD_ISSET(m_fdsets.fd_array[i],&fdtemp)){
                sockWaiter = m_fdsets.fd_array[i];
                //sock--包大小，缓冲区，偏移量
                stru_pack *p =  m_mapSocketToPack[sockWaiter];
                if(!p){
                    //第一次接收 --接收包大小
                     nRecvNum = recv(sockWaiter,(char*)&nPackSize,sizeof(int),0);
                    if(nRecvNum<=0){
                        //客户端下载
                        if(GetLastError() == 10054){
                            closesocket(sockWaiter);
                            //将sockwaiter 从fd_set集合移除
                            FD_CLR(sockWaiter,&m_fdsets);
                        }
                        continue;
                    }
                    p = new stru_pack;
                    p->m_nPackSize = nPackSize;
                    p->m_pszbuf = new char[nPackSize];
                    p->m_noffset = 0;
                    m_mapSocketToPack[sockWaiter] = p;

                }else{
                    //第n次接收的包内容
                    nRecvNum = recv(sockWaiter,p->m_pszbuf+p->m_noffset,p->m_nPackSize,0);
                    p->m_noffset += nRecvNum;
                    p->m_nPackSize-=nRecvNum;
                    if(p->m_nPackSize ==0){
                        //调用IKernel里的dealDate

                        TCPKernel::getKernel()->dealDate(sockWaiter,p->m_pszbuf);
                        delete []p->m_pszbuf;
                        // printf("%s\n",pszbuf);//处理数据
                        delete p;
                         m_mapSocketToPack[sockWaiter] = NULL;
                    }
                }

            }
        }
    }
}


void TCPServer::unInitNetWork(const char *szerr )
{
    m_bFlagQuit = false;
    for (auto& ite:m_lstThread) {

        if(WAIT_TIMEOUT == WaitForSingleObject(ite,100))
            TerminateThread(ite,-1);

        if(ite){
            CloseHandle(ite);
            ite = NULL;
        }
    }
    m_lstThread.clear();
    printf(szerr);
    if(m_socklisten){
       closesocket(m_socklisten);
        m_socklisten = 0;
    }
    WSACleanup();
}

bool TCPServer::sendData(SOCKET sock, const char *szbuf, int nlen)
{
    if(!szbuf || nlen <=0)
        return false;
   //粘包
    //发送包大小
    if(send(sock,(char*)&nlen,sizeof(int),0)<=0)
        return false;
    //发送包内容
    if(send(sock,szbuf,nlen,0)<=0)
        return false;
    return true;
}



